﻿//---------------------------------------------------------------------------
//
// Copyright (C) Inter Access B.V..  All rights reserved.
//
//---------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using Schedule.Primitives;

namespace Schedule
{
    [TemplatePart(Name = "PART_Cells", Type = typeof(ItemsControl))]
    [TemplatePart(Name = "PART_Appointments", Type = typeof(ItemsControl))]
    public class ScheduleChronicalView : Control
    {
        static ScheduleChronicalView()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ScheduleChronicalView), new FrameworkPropertyMetadata(typeof(ScheduleChronicalView)));

            EventManager.RegisterClassHandler(typeof(ScheduleChronicalView), TimePanel.ItemSizeChangedRoutedEvent, new RoutedEventHandler(OnItemSizeChanged));
        }

        public ScheduleChronicalView()
        {
            // Create a new Cell collection
            Cells = new ObservableCollection<ScheduleCell>();
        }

        #region Dependency Properties

        /// <summary>
        /// Date to display
        /// </summary>
        public DateTime Date
        {
            get { return (DateTime)GetValue(DateProperty); }
            set { SetValue(DateProperty, value); }
        }

        public static readonly DependencyProperty DateProperty =
            DependencyProperty.Register("Date", typeof(DateTime), typeof(ScheduleChronicalView), new UIPropertyMetadata(OnDatePropertyChanged));

        private static void OnDatePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            ScheduleChronicalView presenter = (ScheduleChronicalView)sender;
            //presenter.RebuildCells();
        }

        /// <summary>
        /// Appointments to display
        /// </summary>
        public ObservableCollection<Appointment> Appointments
        {
            get { return (ObservableCollection<Appointment>)GetValue(AppointmentsProperty); }
            set { SetValue(AppointmentsProperty, value); }
        }

        public static readonly DependencyProperty AppointmentsProperty =
            DependencyProperty.Register("Appointments", typeof(ObservableCollection<Appointment>), typeof(ScheduleChronicalView), new UIPropertyMetadata());

        /// <summary>
        /// Cells to display
        /// </summary>
        public ObservableCollection<ScheduleCell> Cells
        {
            get { return (ObservableCollection<ScheduleCell>)GetValue(CellsProperty); }
            set { SetValue(CellsProperty, value); }
        }

        public static readonly DependencyProperty CellsProperty =
            DependencyProperty.Register("Cells", typeof(ObservableCollection<ScheduleCell>), typeof(ScheduleChronicalView), new UIPropertyMetadata());

        /// <summary>
        /// DataTemplate for appointments
        /// </summary>
        public DataTemplate AppointmentTemplate
        {
            get { return (DataTemplate)GetValue(AppointmentTemplateProperty); }
            set { SetValue(AppointmentTemplateProperty, value); }
        }

        public static readonly DependencyProperty AppointmentTemplateProperty =
            DependencyProperty.Register("AppointmentTemplate", typeof(DataTemplate), typeof(ScheduleChronicalView), new UIPropertyMetadata());

        #endregion

        private static void OnItemSizeChanged(object target, RoutedEventArgs e)
        {
            // If the itemsize has changed, we need to rebuild cells
            ScheduleChronicalView view = (ScheduleChronicalView)target;
            TimePanel sender = (TimePanel)e.OriginalSource;
            view.RebuildCells(sender.ItemSize);
        }

        public override void OnApplyTemplate()
        {
            // Create and set a filter on the appointment
            // We do not need one for cells, because we create it ourselves
            TimeItemsPresenter appointments = (TimeItemsPresenter)this.GetTemplateChild("PART_Appointments");
            CollectionViewSource appointmentsResource = (CollectionViewSource)appointments.FindResource("Appointments");
            appointmentsResource.Filter += new FilterEventHandler(DateTimeFilter);

            base.OnApplyTemplate();
        }

        /// <summary>
        /// Rebuilds day cells with the specified item size
        /// Foreach timespan an cell gets created
        /// </summary>
        /// <param name="size"></param>
        private void RebuildCells(TimeItemSize size)
        {
            // Clear current cells
            this.Cells.Clear();
            
            // Set the dates
            DateTime workingDate = this.Date;
            DateTime endDate = this.Date.AddDays(1);

            // Daily is not possible, yet :)
            if (size != TimeItemSize.Daily)
            {
                // While we need to generate cells
                while (workingDate < endDate)
                {
                    // Generate a cell!
                    ScheduleCell cell = new ScheduleCell();
                    TimePanel.SetItemStart(cell, workingDate);
                    TimePanel.SetItemEnd(cell, workingDate.AddSeconds((int)size));
                    this.Cells.Add(cell);

                    workingDate = workingDate.AddSeconds((int)size);
                }
            }
        }

        /// <summary>
        /// Filters the appointments in the collection
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DateTimeFilter(object sender, FilterEventArgs e)
        {
            DateTime start;
            DateTime end;

            // Change this into something more generic
            if (e.Item is Appointment)
            {
                Appointment item = (Appointment)e.Item;
                start = item.Start;
                end = item.End;

                bool bool1 = start < this.Date.AddDays(1);
                bool bool2 = end > this.Date; 
                bool bool3 = (end - start).TotalHours < 48;

                if (bool1 && bool2 && bool3)
                {
                    e.Accepted = true;
                    return;
                }
            }
            e.Accepted = false;
        }
    }
}
